package org.stars.util;

/**
 * 
 * String utility
 * 
 * @author Francesco Benincasa
 * 
 */
public abstract class StringUtility {
	/**
	 * Put first letter in uppercase. The other characters will be untouched
	 * 
	 * @param s
	 *            input string
	 * @return output string
	 */
	public static String firstLetterUppercase(String s) {
		if (s == null || s.length() == 0)
			return s;
		if (s.length() == 1) {
			return s.toUpperCase();
		}

		return s.substring(0, 1).toUpperCase() + s.substring(1);
	}

	/**
	 * Put first letter in lowercase. The other characters will be untouched
	 * 
	 * @param s
	 *            input string
	 * @return output string
	 */
	public static String firstLetterLowercase(String s) {
		if (s == null || s.length() == 0)
			return s;
		if (s.length() == 1) {
			return s.toLowerCase();
		}

		return s.substring(0, 1).toLowerCase() + s.substring(1);
	}

	/**
	 * Mette la prima lettera in maiuscolo e tutte le altre in maiuscolo
	 * 
	 * @param s
	 *            stringa in input
	 * @return stringa in output
	 */
	public static String capitalize(String s) {
		if (s == null || s.length() == 0)
			return s;
		if (s.length() == 1) {
			return s.toUpperCase();
		}

		return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
	}

	/**
	 * Mette la prima lettera in minuscolo e tutte le altre in maiuscolo
	 * 
	 * @param s
	 *            stringa in input
	 * @return stringa in output
	 */
	public static String lowerize(String s) {
		if (s == null || s.length() == 0)
			return s;
		if (s.length() == 1) {
			return s.toLowerCase();
		}

		return s.substring(0, 1).toLowerCase() + s.substring(1).toUpperCase();
	}

	/**
	 * Data una stringa, controlla che tale stringa non oltrepassi la dimensione
	 * passata come parametro a questa metodo. Nel caso ciò avvenga, la stringa
	 * di partenza viene tagliata e in coda viene inserita la stringa
	 * <i>elipsis</i>. <BR>
	 * Nel caso in cui la lunghezza desiderata sia minore della lunghezza di
	 * <i>elipsis</i>, quest'ultima non viene inserita in coda.
	 * 
	 * @param src
	 *            stringa iniziale
	 * @param length
	 *            lunghezza che si desidera ottenere
	 * @param elipsis
	 *            stringa da mettere al posto dei caratteri eccedenti.
	 * @return stringa elaborata
	 */
	public static String crop(String src, int length, String elipsis) {
		src = nvl(src);
		elipsis = nvl(elipsis);

		String ret = "";

		if (length <= elipsis.length())
			elipsis = "";

		if (src.length() <= length)
			ret = src;
		else {
			ret = src.substring(0, length - elipsis.length()) + elipsis;
		}

		return ret;
	}

	/**
	 * Data una stringa, controlla che tale stringa non oltrepassi la dimensione
	 * passata come parametro a questa metodo. Nel caso ciò avvenga, la stringa
	 * di partenza viene tagliata e in testa viene inserita la stringa
	 * <i>elipsis</i>. <BR>
	 * Nel caso in cui la lunghezza specificata sia minore della lunghezza di
	 * <i>elipsis</i>, quest'ultima non viene inserita in testa.
	 * 
	 * @param src
	 *            stringa iniziale
	 * @param length
	 *            lunghezza che si desidera ottenere
	 * @param elipsis
	 *            stringa da mettere al posto dei caratteri eccedenti.
	 * @return stringa elaborata
	 */
	public static String rightCrop(String src, int length, String elipsis) {
		src = nvl(src);
		elipsis = nvl(elipsis);

		String ret = "";

		if (length <= elipsis.length())
			elipsis = "";

		if (src.length() <= length)
			ret = src;
		else {
			ret = elipsis + src.substring(length - elipsis.length());
		}

		return ret;
	}

	/**
	 * Data una stringa contenente una lista di elementi separati mediante uno o
	 * più caratteri definiti separatori, questo metodo restituisce un array di
	 * stringhe contenente i vari elementi separati tra loro. A tutti gli
	 * elementi vengono rimossi tutti gli spazi vuoti inutili.
	 * <p>
	 * Nel caso in cui la stringa sia <code>null</code>, viene restituita un
	 * array vuoto, senza elementi.
	 * <p>
	 * Nel caso in cui la stringa non contenga il separatore, viene restituito
	 * un unico elemento.
	 * <p>
	 * 
	 * @param value
	 *            stringa contenente gli elementi
	 * @param separator
	 *            stringa da utilizzare come separatori
	 * @return array di elementi.
	 */
	public static String[] splitList(String value, String separator) {
		value = nvl(value);
		String[] result = value.split(separator);

		// toglie tutti gli spazi vuoti inutili.
		for (int i = 0; i < result.length; i++) {
			result[i] = result[i].trim();
		}

		return result;
	}

	/**
	 * Data una stringa contenente un elenco i cui elementi sono separati da una
	 * virgola ',' restituisce un elenco di elementi senza spazi.
	 * 
	 * @param value
	 *            stringa in input
	 * @return array di stringa ottenuta dalla striga in input
	 * 
	 */
	public static String[] splitList(String value) {
		return splitList(value, ",");
	}

	/**
	 * Data una stringa, aggiunge degli zeri a sinistra fino al raggiungimento
	 * della dimensione inserita come parametro della funzione.
	 * <p>
	 * Nel caso in cui la stringa abbia già raggiunto la lunghezza fornita come
	 * parametro, viene restituita la stringa iniziale.
	 * <p>
	 * Ad esempio, invocando la funzione con i seguenti parametri: <code>
	 * <pre>
	 * StringUtility.fillZeroLeft(&quot;aa&quot;, 6);
	 * </pre>
	 * </code> otteniamo la stringa <code>"0000aa"</code>.
	 * 
	 * @param s
	 *            stringa da modificare
	 * @param size
	 *            dimensione da raggiungere
	 * @return stringa opportunamente rimaneggiata con gli zeri a sinistra.
	 */
	public static String fillZeroLeft(String s, int size) {
		return fillLeft(s, "0", size);
	}

	/**
	 * Data una stringa, aggiunge degli spazi a sinistra fino al raggiungimento
	 * della dimensione inserita come parametro della funzione.
	 * <p>
	 * Nel caso in cui la stringa abbia già raggiunto la lunghezza fornita come
	 * parametro, viene restituita la stringa iniziale.
	 * <p>
	 * Ad esempio, invocando la funzione con i seguenti parametri: <code>
	 * <pre>
	 * StringUtility.fillSpaceLeft(&quot;aa&quot;, 6);
	 * </pre>
	 * </code> otteniamo la stringa <code>"    aa"</code>.
	 * 
	 * @param s
	 *            stringa da modificare
	 * @param size
	 *            dimensione da raggiungere
	 * @return stringa opportunamente rimaneggiata con gli zeri a sinistra.
	 */
	public static String fillSpaceLeft(String s, int size) {
		return fillLeft(s, " ", size);
	}

	/**
	 * Data una stringa, aggiunge degli spazi a destra fino al raggiungimento
	 * della dimensione inserita come parametro della funzione. <br>
	 * Nel caso in cui la stringa abbia già raggiunto la lunghezza fornita come
	 * parametro, viene restituita la stringa iniziale. <br>
	 * Ad esempio, invocando la funzione con i seguenti parametri: <code>
	 * <pre>
	 * StringUtility.fillSpaceLeft(&quot;aa&quot;, 6);
	 * </pre>
	 * </code> otteniamo la stringa <code>"    aa"</code>.
	 * 
	 * @param s
	 *            stringa da modificare
	 * @param size
	 *            dimensione da raggiungere
	 * @return stringa opportunamente rimaneggiata con gli zeri a sinistra.
	 */
	public static String fillSpaceRight(String s, int size) {
		return fillRight(s, " ", size);
	}

	/**
	 * Data una stringa di input, provvede a inserire dei caratteri di
	 * riempimento alla sinistra dei caratteri già presenti nella stringa fino
	 * al raggiungimento della dimensione specificata. La stringa di riempimento
	 * tipicamente è un carattere.<br>
	 * 
	 * La stringa alla fine ha sempre e comunque le dimensioni specificate come
	 * parametro. Nel caso in cui la stringa passata come parametro ha
	 * dimensioni maggiori rispetto alla dimensione originaria..essa viene
	 * troncata, togliendo caratteri a sinistra.<br>
	 * 
	 * Se la stringa <code>filler</code> è <code>null</code>, viene posto a
	 * carattere <code>spazio</code>.
	 * 
	 * @param s
	 *            stringa iniziale
	 * @param filler
	 *            stringa di riempimento
	 * @param size
	 *            dimensione da raggiungere
	 * @return stringa formattata
	 */
	public static String fillLeft(String s, String filler, int size) {
		if (size < 0)
			size = 0;
		if (s == null)
			s = "";
		if (filler == null || filler.length() == 0)
			filler = " ";
		for (; s.length() < size;) {
			s = filler + s;
		}

		int iStart = s.length() - size;
		int iEnd = s.length();

		s = s.substring(iStart, iEnd);

		return s;
	}

	/**
	 * Data una stringa di input, provvede a inserire dei caratteri di
	 * riempimento alla sinistra dei caratteri già presenti nella stringa fino
	 * al raggiungimento della dimensione specificata. La stringa di riempimento
	 * tipicamente è un carattere.<br>
	 * 
	 * La stringa alla fine ha sempre e comunque le dimensioni specificate come
	 * parametro. Nel caso in cui la stringa passata come parametro ha
	 * dimensioni maggiori rispetto alla dimensione originaria..essa viene
	 * troncata, togliendo caratteri a destra.<br>
	 * 
	 * Se la stringa <code>filler</code> è <code>null</code>, viene posto a
	 * carattere <code>spazio</code>.
	 * 
	 * @param s
	 *            stringa iniziale
	 * @param filler
	 *            stringa di riempimento
	 * @param size
	 *            dimensione da raggiungere
	 * @return stringa formattata
	 */
	public static String fillRight(String s, String filler, int size) {
		if (s == null)
			s = "";
		if (filler == null || filler.length() == 0)
			filler = " ";
		for (; s.length() < size;) {
			s = s + filler;
		}

		s = s.substring(0, size);

		return s;
	}

	/**
	 * Restituisce il valore passato come argomento se quest'ultimo non è
	 * <i>null</i>, altrimenti una stringa vuota.
	 * 
	 * @param src
	 *            valore da controllare
	 * 
	 * @return Restuisce una stringa non vuota.
	 */
	public static String nvl(String src) {
		return nvl(src, "");
	}

	/**
	 * Restituisce il valore passato come argomento se quest'ultimo non è
	 * <i>null</i>, altrimenti la stringa di default, ovvero il secondo
	 * parametro.
	 * 
	 * @param src
	 *            valore da controllare
	 * @param sDefault
	 *            valore di default
	 * 
	 * @return Restuisce una stringa non vuota.
	 */
	public static String nvl(String src, String sDefault) {
		if (src == null) {
			return sDefault;
		}

		return src;
	}

	/**
	 * Restituisce l'array passato come argomento se quest'ultimo non è
	 * <i>null</i>, altrimenti un array con 0 elementi.
	 * 
	 * @param valori
	 *            array da controllare
	 * 
	 * @return Restuisce un array non vuota.
	 */
	public static String[] nvl(String[] valori) {
		if (valori == null) {
			return new String[0];
		}

		return valori;
	}

	/**
	 * Data una stringa, sostituisce tutte le istanze di una stringa una sua
	 * sottostringa (<i>oldstr</i>) con una nuova stringa (<i>newstringa</i>).
	 * 
	 * @param src
	 *            stringa su cui effettuare la ricerca.
	 * @param oldstr
	 *            stringa da ricercare.
	 * @param newstr
	 *            nuova sottostringa.
	 * 
	 * @return La stringa <i>src</i> dopo la sostituzione.
	 */
	public static String replaceString(String src, String oldstr, String newstr) {
		if (src == null) {
			return null;
		}

		StringBuffer dest = new StringBuffer("");
		int len = oldstr.length();
		int srclen = src.length();
		int pos;
		int oldpos;

		for (oldpos = 0; (pos = src.indexOf(oldstr, oldpos)) >= 0; oldpos = pos + len) {
			dest.append(src.substring(oldpos, pos));
			dest.append(newstr);
		}

		if (oldpos < srclen) {
			dest.append(src.substring(oldpos, srclen));
		}

		return dest.toString();
	}

	/**
	 * Data una stringa, sostituisce tutte le istanze di una stringa una sua
	 * sottostringa (<i>oldstr</i>) con una nuova stringa (<i>newstringa</i>).
	 * 
	 * @param src
	 *            stringa su cui effettuare la ricerca.
	 * @param oldstr
	 *            stringa da ricercare.
	 * @param newstr
	 *            nuova sottostringa.
	 * 
	 * @return La stringa <i>src</i> dopo la sostituzione.
	 */
	public static String replace(String src, String oldstr, String newstr) {
		if (src == null) {
			return null;
		}

		StringBuffer dest = new StringBuffer("");
		int len = oldstr.length();
		int srclen = src.length();
		int pos;
		int oldpos;

		for (oldpos = 0; (pos = src.indexOf(oldstr, oldpos)) >= 0; oldpos = pos + len) {
			dest.append(src.substring(oldpos, pos));
			dest.append(newstr);
		}

		if (oldpos < srclen) {
			dest.append(src.substring(oldpos, srclen));
		}

		return dest.toString();
	}
	


	/**
	 * Return a string for an integer justified left or right and filled up with
	 * `fill' characters if necessary.
	 * 
	 * @param i
	 *            integer to format
	 * @param length
	 *            length of desired string
	 * @param left_justify
	 *            format left or right
	 * @param fill
	 *            fill character
	 * 
	 * @return formatted int
	 */
	public static String format(int i, int length, boolean left_justify, char fill) {
		return fillUp(Integer.toString(i), length, left_justify, fill);
	}

	/**
	 * Fillup char with up to length characters with char `fill' and justify it
	 * left or right.
	 * 
	 * @param str
	 *            string to format
	 * @param length
	 *            length of desired string
	 * @param left_justify
	 *            format left or right
	 * @param fill
	 *            fill character
	 * 
	 * @return stringa formattata
	 */
	public static String fillUp(String str, int length, boolean left_justify, char fill) {
		if (str == null)
			str = "";
		int len = length - str.length();
		char[] buf = new char[(len < 0) ? 0 : len];

		for (int j = 0; j < buf.length; j++)
			buf[j] = fill;

		if (left_justify) {
			return str + new String(buf);
		} else {
			return new String(buf) + str;
		}
	}

	/**
	 * Data una stringa di input, provvede a inserire dei caratteri di
	 * riempimento alla sinistra dei caratteri gi� presenti nella stringa fino
	 * al raggiungimento della dimensione specificata. La stringa di riempimento
	 * tipicamente è un carattere.<br>
	 * 
	 * La stringa alla fine ha sempre e comunque le dimensioni specificate come
	 * parametro. Nel caso in cui la stringa passata come parametro ha
	 * dimensioni maggiori rispetto alla dimensione originaria..essa viene
	 * troncata, togliendo caratteri a sinistra.<br>
	 * 
	 * Se la stringa <code>filler</code> è <code>null</code>, viene posto a
	 * carattere <code>vuoto</code> e viene restituita la stringa originaria.
	 * 
	 * @param src
	 *            stringa iniziale
	 * @param filler
	 *            carattere di riempimento
	 * @param len
	 *            dimensione da raggiungere
	 * @return stringa formatta
	 */
	public static String lpad(String src, char filler, int len) {
		if (src == null)
			src = "";
		char[] buf = new char[(len < 0) ? 0 : len];

		for (int j = 0; j < buf.length; j++)
			buf[j] = filler;

		src = new String(buf) + src;

		int iStart = src.length() - len;
		// iStart=iStart<0 ? 0 : iStart;

		int iEnd = src.length();
		if (iEnd <= 0)
			return "";

		src = src.substring(iStart, iEnd);

		return src;
	}

	/**
	 * Data una stringa di input, provvede a inserire dei caratteri di
	 * riempimento alla sinistra dei caratteri già presenti nella stringa fino
	 * al raggiungimento della dimensione specificata. La stringa di riempimento
	 * tipicamente è un carattere.<br>
	 * 
	 * La stringa alla fine ha sempre e comunque le dimensioni specificate come
	 * parametro. Nel caso in cui la stringa passata come parametro ha
	 * dimensioni maggiori rispetto alla dimensione originaria..essa viene
	 * troncata, togliendo caratteri a destra.<br>
	 * 
	 * Se la stringa <code>filler</code> è <code>null</code>, viene posto a
	 * carattere <code>vuoto</code> e viene restituita la stringa originaria.
	 * 
	 * @param src
	 *            stringa iniziale
	 * @param filler
	 *            carattere di riempimento
	 * @param len
	 *            dimensione da raggiungere
	 * 
	 * @return stringa formattata
	 */
	public static String rpad(String src, char filler, int len) {
		if (src == null)
			src = "";

		char[] buf = new char[(len < 0) ? 0 : len];

		for (int j = 0; j < buf.length; j++)
			buf[j] = filler;

		src = src + new String(buf);

		if (len <= 0)
			return "";
		// len=len>src.length() ? src.length() : len;

		src = src.substring(0, len);

		return src;
	}

	/**
	 * Data una stringa di input, provvede a inserire dei caratteri di
	 * riempimento alla sinistra dei caratteri già presenti nella stringa fino
	 * al raggiungimento della dimensione specificata. La stringa di riempimento
	 * tipicamente è un carattere.<br>
	 * 
	 * La stringa alla fine ha sempre e comunque le dimensioni specificate come
	 * parametro. Nel caso in cui la stringa passata come parametro ha
	 * dimensioni maggiori rispetto alla dimensione originaria..essa viene
	 * troncata, togliendo caratteri a sinistra.<br>
	 * 
	 * Se la stringa <code>filler</code> è <code>null</code>, viene posto a
	 * carattere <code>vuoto</code> e viene restituita la stringa originaria.
	 * 
	 * @param src
	 *            stringa iniziale
	 * @param filler
	 *            stringa di riempimento
	 * @param len
	 *            dimensione da raggiungere
	 * @return stringa formattata
	 */
	public static String lpad(String src, String filler, int len) {
		StringBuffer buf = new StringBuffer((len < 0) ? 0 : len);

		src = (src == null) ? "" : src;
		filler = (filler == null) ? "" : filler;

		for (int j = 0; j < len; j++)
			buf.append(filler);

		src = buf.toString() + src;

		int iStart = src.length() - len;
		iStart = iStart < 0 ? 0 : iStart;

		int iEnd = src.length();
		if (iEnd == 0)
			return "";

		src = src.substring(iStart, iEnd);

		return src;
	}

	/**
	 * Data una stringa di input, provvede a inserire dei caratteri di
	 * riempimento alla sinistra dei caratteri già presenti nella stringa fino
	 * al raggiungimento della dimensione specificata. La stringa di riempimento
	 * tipicamente è un carattere.<br>
	 * 
	 * La stringa alla fine ha sempre e comunque le dimensioni specificate come
	 * parametro. Nel caso in cui la stringa passata come parametro ha
	 * dimensioni maggiori rispetto alla dimensione originaria..essa viene
	 * troncata, togliendo caratteri a destra.<br>
	 * 
	 * Se la stringa <code>filler</code> è <code>null</code>, viene posto a
	 * carattere <code>vuoto</code> e viene restituita la stringa originaria.
	 * 
	 * @param src
	 *            stringa iniziale
	 * @param filler
	 *            stringa di riempimento
	 * @param len
	 *            dimensione da raggiungere
	 * 
	 * @return stringa in output
	 */
	public static String rpad(String src, String filler, int len) {
		StringBuffer buf = new StringBuffer((len < 0) ? 0 : len);

		src = (src == null) ? "" : src;
		filler = (filler == null) ? "" : filler;

		for (int j = 0; j < len; j++)
			buf.append(filler);

		src = src + buf.toString();

		if (len <= 0)
			return "";
		len = len > src.length() ? src.length() : len;

		src = src.substring(0, len);

		return src;
	}

	/**
	 * Verifica se una stringa è un intero.
	 * 
	 * @param src
	 *            stringa da verificare
	 * @return <code>true</code> se la stringa contiene un intero.
	 */
	public static boolean isInteger(String src) {
		boolean bRet = false;
		try {
			Integer.parseInt(src);
			bRet = true;
		} catch (Exception e) {

		}
		return bRet;
	}

	/**
	 * Verifica se una stringa è un long.
	 * 
	 * @param src
	 *            stringa da verificare
	 * @return <code>true</code> se la stringa contiene un long.
	 */
	public static boolean isLong(String src) {
		boolean bRet = false;
		try {
			Long.parseLong(src);
			bRet = true;
		} catch (Exception e) {

		}
		return bRet;
	}
}
